<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<meta name="vlam" content="">
<title>Sound tutorial</title></head>
<body>
<h1>Sound tutorial</h1>
<p>The following is an outline of a sound tutorial using Crunchy Frog.</p>
<h2>Sound and frequency</h2>
<pre title="editor size=(2, 60)">
play_tone(440, 2)
</pre>
<p>Try a different value for the frequency (e.g. 600, or 200).  
The frequency is related to the <em>pitch</em> of a musical instrument.</p>
<h2>Combining sounds</h2>
<pre title="editor size=(4, 60)">
play_tones((440, 215), 2)
play_tones((440, 215, 600), 2)
play_tones((440, 215, 630, 150, 1477), 2)
</pre>
<p>These tones do not sound nice together.  We will see later what makes for
more pleasant sounding combinations.  But before, we'll have a look at beats.</p>
<h2>Beats</h2>
<pre title="editor size=(2, 60)">
play_tones((440, 441), 4)
</pre>
<p>Try with different values, like (440, 442), etc.  What must be the
difference in value for your ear to perceive them as two completely different sounds?</p>
<h2>Musical notes</h2>
<p>Some blurb about musical notes, the value of their frequences.  Play a song for a demo, then end with combinations of notes.</p>
<h2>Graphical detour: sine wave</h2>
<p>Plotting a single sine wave</p>
<pre title="plot size=(7, 80)">
from math import sin
prepare_graph(x_range=(0, 20), y_range=(-2, 2))
set_line_colour('red')
frequency = 1.
def wave(x):
  return sin(frequency*x)
plot_function(sin)
</pre>
<p>Try to change the frequency to different values (2, 3, 10, ...) or the maximum value of x_range (change it to 100, for example).</p>
<h2>Adding two sine waves</h2>
<p>General case</p>
<pre title="plot">
from math import sin
prepare_graph(x_range=(0, 20), y_range=(-2, 2))
f1 = 1.
f2 = 2.3
def wave1(x):
  return sin(f1*x)
def wave2(x):
  return sin(f2*x)
def wave_sum(x):
  return wave1(x) + wave2(x)
set_line_colour('red')
plot_function(wave1)
set_line_colour('green')
plot_function(wave2)
set_line_colour('blue')
plot_function(wave_sum)
</pre>
<p>Try different values for f1, f2 and the maximum value for x_range</p>
<h2>Beats</h2>
<pre title="plot">
from math import sin
prepare_graph(x_range=(0, 20), y_range=(-2, 2))
f1 = 5.
f2 = 5.3
def wave1(x):
  return sin(f1*x)
def wave2(x):
  return sin(f2*x)
def wave_sum(x):
  return wave1(x) + wave2(x)
set_line_colour('red')
plot_function(wave1)
set_line_colour('green')
plot_function(wave2)
set_line_colour('blue')
plot_function(wave_sum)
</pre>
<p>Try different values for f1, f2 and the maximum value for x_range</p>
<p>You can also visualise something that looks like the beat pattern you
heard before, while listening to it.</p>
<pre title="plot area=(800, 400)">
play_tones((440, 441), 4)
from math import sin
prepare_graph(x_range=(0, 90), y_range=(-2, 2))
f1 = 5.
f2 = 5.3
def wave1(x):
  return sin(f1*x)
def wave2(x):
  return sin(f2*x)
def wave_sum(x):
  return wave1(x) + wave2(x)
set_line_colour('red')
plot_function(wave1)
set_line_colour('green')
plot_function(wave2)
set_line_colour('blue')
plot_function(wave_sum)
</pre>
<h2>Advanced Python: function factory</h2>
<p>Talk of the concept of having a function that defines new functions.</p>
<p>Note that:</p>
<pre>
sin(2*3) = sin(3*2)
</pre>
<p>Proceed with example</p>
<pre title="editor">
from math import sin
def wave_factory(f):
    def wave(x):
        return sin(f*x)
    return wave

wave2 = wave_factory(2)
wave3 = wave_factory(3)
print wave2(3)
print wave3(2)
</pre>
<p>We will make use of this to simplify our code.</p>
<h2>Fourier series</h2>
<p>Equal amplitude sum.</p>
<pre title="plot">
from math import sin
colours = ['black', 'orange', 'green', 'blue', 'indigo', 'pink', 'yellow']
def wave_factory(f):
    def wave(x):
        return sin(f*x)
    return wave
prepare_graph(x_range=(0, 20), y_range=(-5, 5))
waves = [wave_factory(f) for f in range(1, 8)]
for i, wave in enumerate(waves):
  set_line_colour(colours[i])
  plot_function(wave)
def wave_sum(x):
  s = 0
  for wave in waves:
     s += wave(x)
  return s
set_line_colour('red')
plot_function(wave_sum)
</pre>
<p>Triangular wave</p>
<pre title="plot">
from math import sin
colours = ['black', 'orange', 'green', 'blue', 'indigo', 'pink', 'yellow']
coeff = [1, 0, -1./9, 0, 1./25, 0, -1./49, 0, 1./81, 0, -1./121]
def wave_factory(f):
    def wave(x):
        return coeff[f-1]*sin(f*x)
    return wave
prepare_graph(x_range=(0, 20), y_range=(-5, 5))
waves = [wave_factory(f) for f in range(1, 12)]
for i, wave in enumerate(waves):
  set_line_colour(colours[i%7])
  plot_function(wave)
def wave_sum(x):
  s = 0
  for wave in waves:
     s += wave(x)
  return s
set_line_colour('red')
plot_function(wave_sum)
</pre>
<p>Square wave</p>
<pre title="plot">
from math import sin
colours = ['black', 'orange', 'green', 'blue', 'indigo', 'pink', 'yellow']
coeff = [1, 0, 1./3, 0, 1./5, 0, 1./7, 0, 1./9, 0, 1./11]
def wave_factory(f):
    def wave(x):
        return coeff[f-1]*sin(f*x)
    return wave
prepare_graph(x_range=(0, 20), y_range=(-5, 5))
waves = [wave_factory(f) for f in range(1, 12)]
for i, wave in enumerate(waves):
  set_line_colour(colours[i%7])
  plot_function(wave)
def wave_sum(x):
  s = 0
  for wave in waves:
     s += wave(x)
  return s
set_line_colour('red')
plot_function(wave_sum)
</pre>
<p>Sawtooth</p>
<pre title="plot">
from math import sin
colours = ['black', 'orange', 'green', 'blue', 'indigo', 'pink', 'yellow']
coeff = [1, 1./2, 1./3, 1./4, 1./5, 1./6, 1./7, 1./8, 1./9, 1./10, 1./11]
def wave_factory(f):
    def wave(x):
        return coeff[f-1]*sin(f*x)
    return wave
prepare_graph(x_range=(0, 20), y_range=(-5, 5))
waves = [wave_factory(f) for f in range(1, 12)]
for i, wave in enumerate(waves):
  set_line_colour(colours[i%7])
  plot_function(wave)
def wave_sum(x):
  s = 0
  for wave in waves:
     s += wave(x)
  return s
set_line_colour('red')
plot_function(wave_sum)
</pre>
<h2>Harmonics: equal amplitudes</h2>
<pre title="editor size=(3, 60)">
play_tones((220, 440, 660, 880, 1100, 1320), 4)
</pre>
<h2>Sound harmonics</h2>
<p>Same other three cases as above</p>
<pre title="editor size=(5, 120)">
play_harmonics(440, 3, (1,)) # pure tone
play_harmonics(440, 3, (1, 0, -1./9, 0, 1./25, 0, -1./49, 0, 1./81, 0, -1./121)) # triangular
play_harmonics(440, 3, (1, 0, 1./3, 0, 1./5, 0, 1./7, 0, 1./9, 0, 1./11)) # square
play_harmonics(440, 3, (1, 1./2, 1./3, 1./4, 1./5, 1./6, 1./7, 1./8, 1./9, 1./10, 1./11)) # sawtooth
</pre>
<h2>What next?</h2>
<p>Talk about dynamics (varying amplitude with time, etc.) and conclude
that there is a lot more to learn about sound, including white noise, etc.  Perhaps provide a few links to the Internet.</p>
</body>
</html>